import AttributeUtil from '@/AttributeUtil';
import Buff from '@/Buff';
import BuffUtil from '@/BuffUtil';

declare global {
    type AbilityCallBack<T> = (p: { unit: unit; ability: T }) => void;
}

/**
 * 自定义技能基类
 */
export default abstract class AbilityBase {
    private _id: string;
    private _abiblityData: aobj;
    private _abiblityName: string;
    private _art: string;
    constructor(id: string) {
        this._id = id;
        this._abiblityData = _g_objs.ability[this.id];
        this._abiblityName = this._abiblityData.Name;
        this._art = this._abiblityData.Art;
        se.on(GameEvents.技能强化, ({ u }: { u: unit }) => {
            let lv = this.getAbilityLevel(u);
            if (lv == 0) return;
            for (let cb of this._levelChangeListeners) {
                cb.call(this, { unit: u, ability: this });
            }
        });
        se.on(GameEvents.取消技能强化, ({ u }: { u: unit }) => {
            let lv = this.getAbilityLevel(u);
            if (lv == 0) return;
            for (let cb of this._levelChangeListeners) {
                cb.call(this, { unit: u, ability: this });
            }
        });
        BuffUtil.addAnyBuffStackCountChangeListener((buff: Buff, add: number) => {
            if (buff.stackCount == 0) buff.destroy();
        });
    }
    get id() {
        return this._id;
    }
    get abilityName() {
        return this._abiblityName;
    }
    set abilityName(value: string) {
        this._abiblityName = value;
    }
    get art() {
        return this._art;
    }
    set art(value: string) {
        this._art = value;
    }
    get abilityData() {
        return this._abiblityData;
    }
    get ubertip() {
        return this._abiblityData.Ubertip;
    }
    private _levelChangeListeners: Array<AbilityCallBack<any>> = [];
    /**
     * 注册技能等级提升回调
     * @param cb 回调函数
     */
    onLevelChange<T>(cb: AbilityCallBack<T>) {
        this._levelChangeListeners.push(cb);
    }
    /**
     * 给单位添加或者升级技能
     * @param u 目标单位
     */
    addAbility(u: unit) {
        if (GetUnitAbilityLevel(u, this.id) == 0) {
            UnitAddAbility(u, this.id);
        } else {
            IncUnitAbilityLevel(u, this.id);
        }
        this._learnSkillReward(u);

        for (let cb of this._levelChangeListeners) {
            cb.call(this, { unit: u, ability: this });
        }
    }

    // 升级或者添加技能后，给英雄添加1点全属性与10点的生命和5点魔法
    private _learnSkillReward(u: unit, lv: number = 1) {
        AttributeUtil.addUnitAttribute(u, { full_property: 1 * lv, life: 10 * lv, mana: 5 * lv });
    }

    private _removeListeners: Array<AbilityCallBack<any>> = [];
    /**
     * 注册技能移除回调
     * @param cb 回调函数
     */
    onRemove<T>(cb: AbilityCallBack<T>) {
        this._removeListeners.push(cb);
    }

    /**
     * 将目标单位的技能移除
     * @param u 目标单位
     */
    remove(u: unit) {
        let lv = GetUnitAbilityLevel(u, this.id);
        // 当移除技能时，归还奖励的属性
        this._learnSkillReward(u, -1 * lv);
        UnitRemoveAbility(u, this.id);
        for (let cb of this._removeListeners) {
            cb.call(this, { unit: u, ability: this });
        }
    }
    /**
     * 释放技能
     * @param tarX 技能释放点
     * @param tarY 技能释放点
     * @param source 技能来源
     * @param target 技能目标
     * @param data 其它数据
     */
    cast?<T extends Object = any>(tarX: number, tarY: number, source: unit, target: unit, data?: T): void;

    /**
     * 获取单位身上指定技能的强化后的等级
     * @param u 目标单位
     * @returns 强化后的等级
     */
    getAbilityLevel(u: unit) {
        let attr = AttributeUtil.getUnitAttribute(u);
        let level = 0;
        if (attr != null) {
            for (let key in attr) {
                if (key.includes(this.id + `_lv_up`)) {
                    level = attr[key] as number;
                    break;
                }
            }
        }
        let lv = GetUnitAbilityLevel(u, this._id);
        return lv == 0 ? 0 : lv + level;
    }
}
